using System.Diagnostics;
using zhwy.saas.api.Entity.Middleware;
using zhwy.saas.api.Repository;

namespace zhwy.saas.api.Middleware
{
    public class RequestLoggingMiddleware
    {
        private readonly RequestDelegate _next;
        private readonly IServiceProvider _serviceProvider;

        public RequestLoggingMiddleware(RequestDelegate next, IServiceProvider serviceProvider)
        {
            _next = next;
            _serviceProvider = serviceProvider;
        }

        public async Task InvokeAsync(HttpContext context)
        {
            var stopwatch = Stopwatch.StartNew();
            var requestTime = DateTime.Now;

            var originalBodyStream = context.Response.Body;
            using var responseBody = new MemoryStream();
            context.Response.Body = responseBody;

            var requestLog = new RequestLogEntity
            {
                Path = context.Request.Path,
                Method = context.Request.Method,
                Query_string = context.Request.QueryString.ToString(),
                Ip_address = context.Connection.RemoteIpAddress?.ToString(),
                Request_time = requestTime
            };

            // 读取请求体
            if (context.Request.ContentLength > 0)
            {
                context.Request.EnableBuffering();
                using var reader = new StreamReader(context.Request.Body, leaveOpen: true);
                requestLog.Request_body = await reader.ReadToEndAsync();
                context.Request.Body.Position = 0;
            }

            try
            {
                await _next(context);

                stopwatch.Stop();
                requestLog.Execution_time = stopwatch.ElapsedMilliseconds;
                requestLog.Status_code = context.Response.StatusCode;

                // 读取响应体
                responseBody.Position = 0;
                using (var reader = new StreamReader(responseBody, leaveOpen: true))
                {
                    requestLog.Response_body = await reader.ReadToEndAsync();
                }

                // 将响应体复制回原始流
                responseBody.Position = 0;
                await responseBody.CopyToAsync(originalBodyStream);

                // 使用作用域保存日志
                using (var scope = _serviceProvider.CreateScope())
                {
                    var repository = scope.ServiceProvider.GetRequiredService<IBaseRepository<RequestLogEntity>>();
                    await repository.AddAsync(requestLog);
                }
            }
            finally
            {
                context.Response.Body = originalBodyStream;
            }
        }
    }
}